#!/usr/bin/env bash

#-------------------------------------------------
#   File Name：     ${0}
#   Description : 检查并恢复派单api的指定文件
#  Author :       Zampuser
#   date：          2020/7/8
#   version:        1.0.0
#-------------------------------------------------
#   Change Activity:
#                   2020/7/8:
#  只有44运行task任务，其它主机均要删除task目录下的文件
#  除派单主服务44和85,基它服务均要进行文件恢复
#
#  USAGE:
#  SALT命令：
#  salt -N 'pdapiGroup' state.sls prod.item_paidan_api_files runas=amos
#  salt -N 'pdapiGroup' state.sls prod.item_paidan_api_files stop
#-------------------------------------------------


work_date=$(date +%Y%m%d)
work_time=$(date +%H%M%S)
work_dir=$(cd "$(dirname "$0")";pwd)
cd "${work_dir}"
LOCKfile=/tmp/.$(basename $0).pid

function echo_c(){
    action_code=1
    case $1 in
        y)
            echo_log "\033[33;1m" "${*:2:$#}" "\033[0m"
            ;;
        r)
            echo_log "\e[31;1m" "${*:2:$#}" "\e[0m"
            ;;
        *)
            echo_log "\E[32;1m" "${*:2:$#}" "\E[0m"
        ;;
    esac
}

function echo_log(){
    if [[ ${action_code} -eq 0 ]];then
        echo -e "[$(date +%Y%m%d_%H:%M:%S) $$] $2" | tee -a $0.log
    else
        echo -e "$1[$(date +%Y%m%d_%H:%M:%S.%s) $$] $2 $3" | tee -a $0.log
    fi
}

echo_title(){
    # pycharm模板，使用时需要去除#和{}的转义符
    text="${*}"
    line_max_len=60
    line_text_max_len=52
    char_echo="#"
    line=$(seq -s ${char_echo} ${line_max_len}|sed -E 's/[0-9]//g')
    echo_c y ""
    echo_c y ${line}

    text_len=${#text}
    start_line_count=0
    if [[ "${text_len}" -gt "${line_text_max_len}" ]];then
        line_num=$(expr ${text_len} / ${line_text_max_len})
        line_text_max_end=${line_text_max_len}
        for n in $(seq 1 +1 ${line_num});do
            texts="$\{text:$start_line_count:$line_text_max_end\}"
            if [[ $n -eq 1 ]];then
                echo_c y "\#\#  ${texts} \ "
            else
                echo_c y "\#\#\t${texts} \ "
            fi
            start_line_count=$line_text_max_end
            line_text_max_end=$line_text_max_len
        done

        last_line=$(expr ${text_len} % ${line_text_max_len})
        if [[ $last_line -ne 0 ]];then
            echo_c y "\#\#\t$\{text:0-$last_line\}"
        fi
    else
        echo_c y "\#\#  $\{text\}"
    fi

    echo_c y ${line}
}

check_error(){
    if [[ $1 -ne 0 ]];then
        echo_c r "$2:$3"
        echo "$2:$3"
        exit 1
    fi
}

check_code(){
  if [[ $1 -ne 0 ]];then
    echo_c r "$1:$2:$3"
    # continue
  fi
}

# check lock file, one time only let the script run one time
check_lockfile(){
    case $1 in
    start)
        if [ -f "$LOCKfile" ];then
            check_error 1 1 "The script is already exist, please next time to run this script"
        else
          echo_c g "No lock file, begin to create lock file and continue"
          self_pid=$(ps -auxfww|grep -v grep|grep $(basename $0)|awk -F ' ' 'NR==1{print $2}')
          echo ${self_pid} > $LOCKfile
        fi
        ;;
    stop)
        if [ -f "$LOCKfile" ];then
            rm -rf "$LOCKfile"
        else
            echo_c y "No lock file, exit..."
        fi
        ;;
    *)
        check_error 1 1 "[check_lockfile] USEAGE: check_lockfile [ start | stop ]"
        ;;
    esac
}

check_node(){
    if [[ $(echo ${1::1}) == "#" ]];then
        return 1
    else
        return 0
    fi
}

#check_lockfile 'start'
##trap "check_lockfile stop " EXIT TSTP TERM HUP
#trap "check_lockfile stop " SIGKILL SIGINT SIGTERM SIGQUIT SIGHUP

run_user='amos'
[ $(id -aun) != ${run_user} ] && { check_error 9 1 "Error: You must be ${run_user} to run this script"; exit 1; }

echo_c g "开始运行脚本..."


#================================ 配置 ================================
bak_dir=/var/bh/bak/paidan_api_check

#字段1: ip(多个路径写多行);
#字段2:文件根路径;
#字段3: 检测删除目录,0:清空目录,1:删除更新文件,与目录以'@'分隔;多个文件按'|'分隔;
#字段4: 需要恢复的文件,多个文件按'|'分隔;
host[0]="172.36.19.85:/var/bh/app/paidan-api:0@app/Tasks:"
host[1]="172.36.19.85:/var/bh/app/paidan-api-yq:0@app/Tasks:app/Middlewares/AuthMiddleWare.php|app/Controllers/Web/OpenApiController.php"
host[2]="172.36.19.86:/var/bh/app/paidan-api:0@app/Tasks:app/Middlewares/AuthMiddleWare.php|app/Controllers/Web/OpenApiController.php"
host[3]="172.36.19.101:/var/bh/app/paidan-api:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
host[4]="172.36.19.101:/var/bh/app/paidan-api-readonly2:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
host[5]="172.36.19.101:/var/bh/app/paidan-api-readonly3:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
host[6]="172.36.19.93:/var/bh/app/paidan-api:0@app/Tasks:"
host[7]="172.36.19.94:/var/bh/app/paidan-api:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
host[8]="172.36.19.95:/var/bh/app/paidan-api:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
host[9]="172.36.19.96:/var/bh/app/paidan-api:0@app/Tasks:app/Middlewares/AuthMiddleWare.php"
#host[10]="192.168.150.7:/var/bh/app/paidan-api:0@app/Tasks:"
host[11]="192.168.150.7:/var/bh/app/paidan-api-yq:0@app/Tasks:app/Middlewares/AuthMiddleWare.php|app/Controllers/Web/OpenApiController.php"

curr_host=$(ifconfig|grep -v grep|grep -A2 ens33|awk -F ' ' '{if($1=="inet")print $2}')

function link_path(){
  dest_path=$1
  new_path=$2
  if [[ -z "${dest_path}" ]];then
    dest_path="${dest_path}"
  else
    dest_path="${dest_path},${new_path}"
  fi
  echo ${dest_path}
}
function resolve_host(){
  host_msg=$1

  IFS_OLD="$IFS"
  IFS=':'
  arr=(${host_msg})
  IFS="$IFS_OLD"

  ip=${arr[0]}
  root_dir=${arr[1]}
  remove_opt=${arr[2]}
  rollback_opt=${arr[3]}

  if [[ -z "${ip}" ]];then
    check_error 0 3 "未指定主机IP，请检查配置host数组!!![${host_msg}]"
  fi
  if [[ -z "${root_dir}" ]];then
    check_error 0 3 "未指定检测根目录，请检查配置host数组!!![${host_msg}]"
  fi
  if [[ -z "${remove_opt}" ]] && [[ -z "${rollback_opt}" ]];then
    echo_c r "未指定检测目录及文件，请检查配置host数组!!![${host_msg}]"
    continue
  fi
}

function resolve_for(){
  root_path_list=''
  host_data=''
  for m in ${host[@]};do
    resolve_host "${m}"
    if [[ "${curr_host}" == "${ip}" ]];then
      host_data="$(link_path ${host_data} ${m})"
      if [[ -n "${remove_opt}" ]];then
        root_path_list="$(link_path ${root_path_list} ${root_dir}/${remove_opt##*@})"
      fi
      if [[ -n "${rollback_opt}" ]];then
        for rp in $(echo ${rollback_opt}|sed 's/|/ /g');do
          root_path_list="$(link_path ${root_path_list} ${root_dir}/$(dirname ${rp}))"
        done
      fi
    fi

  done
}

function create_dir(){
  if [[ ! -d ${1} ]];then
    mkdir -p $1
    check_code $? 1 "创建目录失败!!![${1}]"
  fi
}
function handle_remove_path(){
  pass

}


resolve_for
host_data_tunp=(${host_data//,/ })
echo_c y "监控条目: ${host_data_tunp}"
item_files=${root_path_list//,/ }
echo_c y "监控文件: ${item_files}"
inotifywait -m -e modify,moved_to,create ${item_files} |
  while read path event file;
    do
#      echo_c y "###"
#      echo_c y "监控条目: ${host_data_tunp}"
#      echo_c y "监控文件: ${item_files}"
#      echo_c y "文件状态发生改变:[${path}${file}], event:[${event}]"
#      echo_c y "path: ${path}"
#      echo_c y "event: ${event}"
#      echo_c y "file: ${file}"
#      echo_c y "###"

      curr_time=$(date +"%F_%H%M%S")
      check_remove_file=""
      for m in ${host_data_tunp[@]};do
        # set $(echo $m|sed 's/:/ /g')
        # 解析数组
        resolve_host ${m}

        if [[ -z "${remove_opt}" ]] && [[ -z "${rollback_opt}" ]];then
          echo_c r "未指定检测目录及文件，请检查配置host数组!!![${host_msg}]"
          continue
        fi
        bak_path="${bak_dir}"/${root_dir//\//_}"/${curr_time}"/
        create_dir "${bak_path}"

        # 处理第三个字段，file and dir
        if [[ -n "${remove_opt}" ]];then
          if [[ "${path}" == "$root_dir"/"${remove_opt##*@}"/ ]];then

            if [[ "${remove_opt%%@*}" == 0 ]];then
              # 清空目录
              echo_c y "文件状态发生改变:[${path}${file}], event:[${event}]"
              echo_c g "清理目录 [${path}]."

              echo_c y "ip: ${ip}"
              echo_c y "root_dir:${root_dir}"
              echo_c y "remove_opt:${remove_opt}"
              echo_c y "rollback_opt:${rollback_opt}"

              for f in $(ls "$path");do
                his_f="${path}""${f}"
                echo_c g "发现历史文件 [${his_f}]."
                echo_c g "移动文件到 [${bak_path}]."
                mv "${his_f}" ${bak_path}
                check_code $? 2 "备份历史文件失败!!![${his_f} -> ${bak_path}]"
              done
              echo_c g "清理目录文件完成 ."

            elif [[ "${remove_opt%%@*}" == 1 ]];then
              # 清理文件
              #handle_remove_file
              echo_c y "文件状态发生改变:[${path}${file}], event:[${event}]"

              file_path="${path}""${file}"
              echo_c g "清理目录文件 [${file_path}]."

              echo_c y "ip: ${ip}"
              echo_c y "root_dir:${root_dir}"
              echo_c y "remove_opt:${remove_opt}"
              echo_c y "rollback_opt:${rollback_opt}"

              if [[ -f "${file_path}" ]];then
                echo_c g "发现更新文件 [${file_path}], 状态: [${event}]."

                echo_c g "移动文件到 [${bak_path}]."
                mv "${file_path}" "${bak_path}"
                check_code $? 2 "备份更新文件失败!!![${file_path} -> ${bak_path}]"
              fi
              echo_c g "请理更新文件完成 ."
            else
              echo_c r "第三字段code配置错误只支持0和1，请检查配置host数组!!![${m}]"
            fi
            continue
          fi
        else
          echo_c y "未配置清理目录!!!"
        fi

        # 处理第四个字段，file
        # 将文件进行恢复，规则：同级目录下后缀为.bak的同名文件
        if [[ -n "${rollback_opt}" ]];then
          echo_c y "文件状态发生改变:[${path}${file}], event:[${event}]"
          change_file=""
          for cfg_file in ${rollback_opt//|/ };do
            if [[ "${path}" == "$root_dir"/$(dirname "$cfg_file")/ ]];then
              if [[ "${file}" == $(basename "${cfg_file}") ]];then
                change_file="$root_dir"/"$cfg_file"
              fi
            fi
          done
          # echo_c y "change_file file:${change_file}"

          if [[ -z "$change_file" ]];then
            continue
          fi
          echo_c g "恢复文件 [${change_file}]."

          old_file="${change_file}".bak
          if [[ ! -f "${old_file}" ]];then
            echo_c r "备份文件不存在!!![${old_file}]"
            continue
          fi

          old_md5=$(md5sum "${old_file}"|cut -d ' ' -f 1)
          new_md5=$(md5sum "${change_file}"|cut -d ' ' -f 1)
          echo_c y "old_md5: ${old_md5},  new_md5: ${new_md5}"
          if [[ ${new_md5} == ${old_md5} ]];then
            echo_c g "文件MD5一至，无需还原."
            continue
          fi

          echo_c y "ip: ${ip}"
          echo_c y "root_dir:${root_dir}"
          echo_c y "remove_opt:${remove_opt}"
          echo_c y "rollback_opt:${rollback_opt}"

          echo_c g "cp -rf ${change_file} ${bak_path}"
          cp -rf "${change_file}" "${bak_path}"
          check_code $? 1 "备份更新文件失败!!![${change_file} -> ${bak_path}]"

          echo_c g "cp -rf ${old_file} ${change_file}"
          cp -rf "${old_file}" "${change_file}"
          check_code $? 1 "还源更新文件失败!!![${old_file} ${change_file}]"
          echo_c g "恢复文件完成 ."
        else
          echo y "未配置监测目录!!!"
        fi
      done
  done
